package com.lckd.ss.metadata.provider;

import com.lckd.ss.dto.DTOUtils;
import com.lckd.ss.dto.IDTO;
import com.lckd.ss.metadata.*;
import com.lckd.ss.util.POJOUtils;
import org.apache.commons.collections4.CollectionUtils;

import java.util.*;

/**
 * 数据字典DataDictionaryValueProvide批量提供者
 */
public abstract class BatchMultiValueProvider implements BatchValueProvider {
    //    主DTO与关联DTO的关联(java bean)属性，即外键
    protected static final String FK_FILED_KEY = "_fkField";
    /**
     * 设置转换列表值
     * @param list
     * @param metaMap
     * @param fieldMeta
     */
    @Override
    public void setDisplayList(List list, Map metaMap, ObjectMeta fieldMeta) {
        List<ValuePair<String>> valuePairs = getFkList(list, metaMap, fieldMeta);
        if (CollectionUtils.isEmpty(valuePairs)) {
            return;
        }
        //key为字段值，所以可能是Integer，String等类型, value为字段的显示值
        Map<String, String> ddv = new HashMap<>(valuePairs.size());
        for (ValuePair<String> valuePair : valuePairs) {
            ddv.put(valuePair.getValue(), valuePair.getText());
        }
        String fkField = metaMap.get(ValueProvider.FIELD_KEY).toString();
        for (Object obj : list) {
            Map<String, Object> map = (Map)obj;
            Object oriObj = map.get(fkField);
            if (oriObj == null) {
                continue;
            }
            //原始值，以逗号分隔
            String oriValue = oriObj.toString();
            map.put(fkField, getConvertedValue(oriValue, ddv));
            map.put(ValueProviderUtils.ORIGINAL_KEY_PREFIX+fkField, oriValue);
        }
    }

    /**
     * 获取外键列表
     * @param list
     * @param metaMap
     * @param fieldMeta
     * @return
     */
    protected abstract List<ValuePair<String>> getFkList(List list, Map metaMap, ObjectMeta fieldMeta);

    /**
     * 将以逗号分隔的数据字典值编码，转换为以逗号分隔的数据字典值名称
     * @param oriValue
     * @return
     */
    private String getConvertedValue(String oriValue, Map<String, String> ddv) {
        String[] split = oriValue.trim().split(",");
        StringBuilder sb = new StringBuilder();
        for (String s : split) {
            String name = ddv.get(s);
            sb.append(name == null ? s : name).append(",");
        }
        return sb.substring(0, sb.length()-1);
    }

    /**
     * 构建DTO列表的单个关联id，为子类提供参考实现
     * @param list
     * @param metaMap
     * @return
     */
    protected List<String> buildRelationIdList(List list, Map metaMap){
        String fkField = getFkField(metaMap);
        Set<String> relationIds = new HashSet();
        for (Object obj : list) {
            Object fkValue = getObjectValueByKey(obj, fkField);
            if (fkValue == null) {
                continue;
            }
            //去重后的外值id
            List<String> relationIdSplits = Arrays.asList(fkValue.toString().split(","));
//            List<String> distinctFkValues = relationIdSplits.stream().flatMap(t -> Arrays.stream(t.trim().split(",")))
//                .distinct().collect(Collectors.toList());
            for (String relationIdSplit : relationIdSplits) {
                relationIds.add(relationIdSplit);
            }
        }
        return new ArrayList<>(relationIds);
    }


    /**
     * 主DTO与关联DTO的关联(java bean)属性(外键)
     * 先从_fkField属性取，没取到再取field属性
     * 子类可自行实现
     * @return
     */
    protected String getFkField(Map metaMap) {
        String field = (String)metaMap.get(FIELD_KEY);
        String fkField = (String)metaMap.get(FK_FILED_KEY);
        return fkField == null ? field : fkField;
    }

    /**
     * 根据key获取对象中的属性，key支持obj.field形式
     * @param obj
     * @param key
     */
    private Object getObjectValueByKey(Object obj, String key){
        if(obj instanceof Map){
            Map map = (Map)obj;
            return map.get(key);
        }else if(IDTO.class.isAssignableFrom(DTOUtils.getDTOClass(obj))){
            //代理类
            if(DTOUtils.isProxy(obj)){
                return ((IDTO) obj).aget(key);
            }//实例类
            else{
                return POJOUtils.getProperty(obj, key);
            }
        }
        //其它javaBean
        return POJOUtils.getProperty(obj, key);
    }

    /**
     * 未使用
     * @param val
     * @param metaMap
     * @param fieldMeta
     * @return
     */
    @Override
    public String getDisplayText(Object val, Map metaMap, FieldMeta fieldMeta) {
        return null;
    }

}